package com.junhong.forum.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.EJB;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Timeout;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

import com.junhong.forum.entity.ForumThread;
import com.junhong.forum.entity.ThreadDashBoard;
import com.junhong.util.StringUtil;

/**
 * Session Bean implementation class DashBoardService
 */

@Named
@ApplicationScoped
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Lock(LockType.READ)
public class ThreadDashBoardCacheService {

	@EJB
	private CategoryServiceSingleton			categoryEjb;
	private Map<String, List<ThreadDashBoard>>	categoryThreadsMap		= new ConcurrentHashMap<String, List<ThreadDashBoard>>();
	private String[]							allCategoryArray		= null;
	@EJB
	private GenericCRUDService<ThreadDashBoard>	genericCRUDService;

	@EJB
	private ThreadEjb							threadEjb;

	private List<ThreadDashBoard>				allDashBoardThreads		= null;
	private List<ForumThread>					mostRecentThreadList	= new ArrayList<ForumThread>();

	/**
	 * Default constructor.
	 */
	public ThreadDashBoardCacheService() {
		// TODO Auto-generated constructor stub
	}

	@PostConstruct
	public void init() {

		categoryThreadsMap.clear();
		allDashBoardThreads = genericCRUDService.findAll(ThreadDashBoard.class);

		int categoryId = -999999;
		int tempCategoryId = 0;
		List<ThreadDashBoard> dashbaords = null;
		String categoryName = null;
		for (ThreadDashBoard db : allDashBoardThreads) {
			// check the CategoryID is changed
			tempCategoryId = db.getCategoryId();
			if (categoryId != tempCategoryId) {
				categoryId = tempCategoryId;
				dashbaords = new ArrayList<ThreadDashBoard>();
				categoryName = categoryEjb.getForumCategoryById(tempCategoryId).getCategoryName();
				categoryThreadsMap.put(categoryName, dashbaords);

				dashbaords.add(db);
			} else {
				dashbaords.add(db);
			}

		}

		// populate category name array.
		Set<String> result = categoryThreadsMap.keySet();
		this.allCategoryArray = new String[result.size()];
		result.toArray(allCategoryArray);

		// get the most recent threads
		mostRecentThreadList = threadEjb.getMostRecentThread(15);

	}

	@Timeout
	@Schedule(dayOfMonth = "*", month = "*", year = "*", second = "*", minute = "0/10", hour = "*")
	public void refreshCache() {
		init();

	}

	/**
	 * @return the categoryThreadsMap
	 */
	public Map<String, List<ThreadDashBoard>> getCategoryThreadsMap() {
		return categoryThreadsMap;
	}

	/**
	 * @param categoryThreadsMap
	 *            the categoryThreadsMap to set
	 */
	public void setCategoryThreadsMap(Map<String, List<ThreadDashBoard>> categoryThreadsMap) {
		this.categoryThreadsMap = categoryThreadsMap;
	}

	public List<ThreadDashBoard> getDashBoards(String categoryName) {
		return categoryThreadsMap.get(categoryName);
	}

	public int getCategoryId(String categoryName) {
		if (StringUtil.isNullOrBlank(categoryName)) {
			return 0;
		}
		return getDashBoards(categoryName).get(0).getCategoryId();
	}

	/**
	 * @return the allCategoryArray
	 */
	public String[] getAllCategoryArray() {
		return allCategoryArray;
	}

	/**
	 * @param allCategoryArray
	 *            the allCategoryArray to set
	 */
	public void setAllCategoryArray(String[] allCategoryArray) {
		this.allCategoryArray = allCategoryArray;
	}

	public List<ThreadDashBoard> getAllDashBoardThreads() {
		return allDashBoardThreads;
	}

	public void setAllDashBoardThreads(List<ThreadDashBoard> allDashBoardThreads) {
		this.allDashBoardThreads = allDashBoardThreads;
	}

	public List<ForumThread> getMostRecentThreadList() {
		return mostRecentThreadList;
	}

	public void setMostRecentThreadList(List<ForumThread> mostRecentThreadList) {
		this.mostRecentThreadList = mostRecentThreadList;
	}
}
